package com.xiaoai.es.tow;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.Configuration;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

public class ESClient {

  private final Configuration configuration;

  public ESClient(Configuration configuration) {
    this.configuration = configuration;
  }

  /**
 * 生成DSL语句
 * 
 * @param mapperId
 * @param param
 * @return
   */
  private String generateDsl(String mapperId, Object param) {
    MappedStatement statement = configuration.getMappedStatement(mapperId);
    return statement.getBoundSql(param).getSql();
  }

  /**
 * 发送http请求进行查询
 * 
 * @param index
 * @param dslStr
 * @return
   */
  private String sendQuery(String index, String dslStr) {
    try {
      String authorization = "Basic "
          + Base64.encodeBase64String(("ES集群用户名" + ":" + "ES集群密码").getBytes("UTF-8"));
      HttpHeaders headers = new HttpHeaders();
      headers.set("Authorization", authorization);
      headers.set("Content-Type", "application/json; charset=UTF-8");
      String url = "http://127.0.0.1:9200/" + index + "/_search";
      HttpEntity<String> requestEntity = new HttpEntity<String>(dslStr, headers);
      RestTemplate restTemplate = new RestTemplate();
      return restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class).getBody();
    } catch (UnsupportedEncodingException e) {
      return null;
    }
  }

  /**
 * 解析查询结果【简单查询解析，聚合查询需要类似的解析】
 * 
 * @param responeJsonStr
   */
  private List<JSONObject> parse(String responeJsonStr) {
    JSONObject resultJson = JSONObject.parseObject(responeJsonStr);
    List<JSONObject> results = new ArrayList<JSONObject>();
    if (resultJson.containsKey("hits")) {
      JSONArray innerHits = resultJson.getJSONObject("hits").getJSONArray("hits");
      /* 剔除外层元数据，组装最后结果集 */
      for (Object hit : innerHits) {
        JSONObject result = ((JSONObject) hit).getJSONObject("_source");
        if (result != null) {
          results.add(result);
        }
      }
    }
    return results;
  }

  /**
   * @param mapperId mapper 的 Sql Id
   * @param param DSL 语句中的参数
   * @param index 索引名
   */
  public List<JSONObject> query(String mapperId, Object param, String index) {
    String dslStr = this.generateDsl(mapperId, param);
    String responeStr = this.sendQuery(index, dslStr);
    return this.parse(responeStr);
  }
}